HAOJX

容器核心技术--chroot ,namespace,cgroups,LCX,和docker

字数统计: 2.1k阅读时长: 7 min
2017/05/25 Share

虚拟化的发展

  • 主机级虚拟化
  • 容器级虚拟化

开始是jail , 用来隔离进程 ,起到安全的作用 , 之后有人把这个功能移植到了unix上 , 叫着vserver , 其中有个重要的功能就是chroot

chroot

chroot意味着切根 , 原来的根是在/ ,有了chroot技术的话 , 就可以把根切到别的地方,这个地方有和根一样的基于FHS定于的目录 ,之后运行进程 , 进程就以为这就是根了 , 这样就实现一个类似于虚拟机的环境 , 但是这样做也有问题 , 这并不能实现与其他用户和宿主机的彻底隔离 , 其实这个虚拟的环境用的还是宿主机的内核 , 那这个虚拟的环境要运行指令的时候, 是要运行特权指令和还是普通的 , 要访问特权资源的时候 , 要怎么指派呢 , 这都是问题 ,

用户空间的主要用途是实现用户进程隔离的, 而且运行在当前用户空间的任何用户进程是以为自己运行在内核空间之上用户空间中的唯一进程, 而且自己看到的进程也应该是这个系统上的全部进程了 , 但是 , 一个用户空间得以下组件:

  • UTS

    主机名和域名

  • Mount

    根文件系统

  • UTS

    每个用户空间的IPC专有通道 , 若是2个用户空间可以互相通信, 这就隔离没有了意义, 所以要确保2个用户空间的IPC是独立的

  • PID

    一个系统运行是基于2颗”树” , 一个是进程树 , 一个是文件系统树 , 所以 在一个用户空间上 ,一个进程要么是init , 一个是属于某个进程的子进程 , 在虚拟用户空间上 , 我们要营造一个假象 , 让里面的进程以为自己是init或者是属于某个进程的子进程 , 但是一个主机上又只能有一个init , 其他进程都是init的子进程 或者子子进程 , 进程的消灭也得由其父进程进行消灭 , 所以 , 在每个虚拟的用户空间上 , 都得有一个init进程 , 但事实上init只能有一个 , 那就是宿主机的init , 所以只能在每个用户空间上做一个假的init , 在这个用户空间上只有一个进程 , 那就是假的init , 这个假的init消失 , 所有进程也都得消失 , 所以,在每个虚拟用户空间上得有自己专有的PID

  • User

    一个虚拟的用户空间得有一个root , 但是一个内核只能有一个root , 那就是宿主机的root , 所以我们只能在每个用户空间上虚造一个root , 这个root在内核看来只是一个普通的进程而已 ,但是对于这个虚拟用户空间来说 , 他有全部权限,对这个虚拟用户空间的进程来说, 这个假的root就是真root

  • Network

    每个虚拟的用户空间都以为自己是这个系统上的唯一的用户空间 , 所以对于虚拟用户空间来说 , 它得有自己的ip , 网络协议栈 , 80端口等 , 而且2个互相不同的虚拟用户空间还得互相通信调度

Namespace

在内核上 , 内核可以用过名称空间(namespace) 来将上述组件进行资源隔离 , 可以在每个用户空间上创建一个UTS等等组件 ,每个名称空间这些资源都是互相隔离的 , 为了支持容器 , Linux在内核上通过一个叫namespace的机制 , 可以把这个上述6个组件通过内核原生支持 , 它可以通过系统调用 ,向外进行输出 , namespace 创建一个进程用clone() , 把这个进程放到一个名称空间中 用setns() , 所以要想用容器的技术 ,虚拟用户空间 ,隔离进行 ,必须得用到内核 ,而内核的版本也是有要求的 ,下面给出的各个版本要求

Linux Namespaces

namespace 系统调用参数 隔离内容 内核版本
UTS CLONE_NEWUTS 主机或域名 2.6.19
IPC CLONE_NEWIPC 信号量,消息队列和共享内存 2.6.19
PID CLONE_NEWPID 进程编号 2.6.24
Network CLONE_NEWNET 网络设备,网络栈,端口等 2.6.29
Mount CLONE_NEWNS 挂载点(文件系统) 2.6.19
User CLONE_NEWUSER 用户和用户组 3.8

Control Groups(cgroups)

每个虚拟空间的进程都是消耗资源的, 我们得限制每个资源使用总量 , 要是不限制的话 , 第一个用户空间如果把资源使用完的话, 第二个,第三个就无法使用了 , 如果内存泄漏什么的 , 就会oom , 所以必须在内核上针对每个用户空间来实现一种机制——>限制资源的消耗 , 这种机制在内核上的实现需要依靠control groups(cgroup)

cgroups把系统上的资源分成多个组 , 每个组上的量分配到每个用户空间上去

cgroups的分组

cgroups

  • blkio 块设备IO
  • cpu
  • cpuacct CPU资源报告
  • cpuset 多处理器平台上的CPU集合
  • devices 设备访问
  • freezer 挂起或恢复任务
  • memory
  • perf_event 对cgroup中的任务进行统一性能测试
  • net_cls croup中的任务创建的数据报文的类别标识符

LXC LinuX Container

有了上述技术我们就可以使用容器了 , 但是还是有门槛 ,为了进一步降低使用门槛 , 有人就把这些技术组装在一起 , 叫做LinuX Container也叫lxc

lxc如何创建一个容器呢

首先lxc 会用一个命令lxc-create来创建一个容器或者一个用户空间 , 创建完用户空间完之后 , 里面还得有什么基本的命令之类的 , 比如ls ,cat 等等 ,这些该如何创建呢 , 或者是我们想创建出一个和宿主机不同系统的用户空间 , 那该怎么办呢 , 这个时候template 的派上用场了 , 可以使用模板来创建 , 于是这个名称空间就可以像使用虚拟机一样来使用了

Docker

docker的lxc的二次封装版 , 比lxc有所提高 , docker利用lxc做容器管理引擎 , 在创建用户空间的时候不是再用模板来生成了 ,而是使用镜像技术

把用户空间所有用到的所有东西都打包成一份 , 打包成的这个东西叫着image , 镜像 , 比如想用一个nginx , 就可以把最小份的系统里安装上nginx , 之后再打包成镜像 , 放到这个仓库中 , 让大家使用

把所有日常用到的镜像 , 放在互联网上一个大家都知道的地方 这个地方叫着仓库 , 在创建容器的时候再把它从仓库下载下来创建 , docker在使用lxc-create的时候不会在使用模板来创建 ,而且用镜像来创建 , 这个镜像是从仓库中拉取过来的 , 使用镜像启动容器 , 所以docker极大的简化了启动容器的方法

docker是希望一个容器只运行一个进程 , 而lxc是把一个用户空间当成一个容器 , 里面可以运行多个进程, docker这种一个容器运行一个进程的方法给运维带来不便 , 比如查看进程 , 内存等等 , 之前查看进程 大家都在一个用户空间中 可以使用ps等命令查看 , 但是有了容器的话, 还得一个一个进入容器内去查看 , 但是相对给开发带来方便 , 实现了一次编译到处运行 , 就不用纠结操作系统等限制了, 不用再开发另外版本了

docker使用”镜像分层 , 联合挂载”来运行容器 , 容器的数据保存在外部 , 可以在外部挂载持久性存储 , 就算是容器挂了 ,再起一个容器即可 , 数据不会丢失 , 这样容器的运行就好比一个进程了, 进程终止, 数据也不会消失

容器编排工具

  • machine+swarm+compose
  • mesos+marathon
  • kubernetes
CATALOG
  1. 1. 虚拟化的发展
    1. 1.1. chroot
    2. 1.2. Namespace
      1. 1.2.1. Linux Namespaces
    3. 1.3. Control Groups(cgroups)
    4. 1.4. LXC LinuX Container
    5. 1.5. Docker
    6. 1.6. 容器编排工具